#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause

from litex.build.generic_platform import *
from litex.build.xilinx import XilinxUSPPlatform, VivadoProgrammer

# IOs ----------------------------------------------------------------------------------------------

_io = [
    # Clk / Rst
    ("rst",    0, Pins("G13"), IOStandard("LVCMOS18")),
    ("clk125", 0,
        Subsignal("p", Pins("H9"), IOStandard("DIFF_SSTL15")),
        Subsignal("n", Pins("G9"), IOStandard("DIFF_SSTL15")),
    ),

    # Leds
    ("user_led", 0, Pins("AL11"), IOStandard("LVCMOS12")),
    ("user_led", 1, Pins("AL13"), IOStandard("LVCMOS12")),
    ("user_led", 2, Pins("AK13"), IOStandard("LVCMOS12")),
    ("user_led", 3, Pins("AE15"), IOStandard("LVCMOS12")),
    ("user_led", 4, Pins("AM8"),  IOStandard("LVCMOS12")),
    ("user_led", 5, Pins("AM9"),  IOStandard("LVCMOS12")),
    ("user_led", 6, Pins("AM10"), IOStandard("LVCMOS12")),
    ("user_led", 7, Pins("AM11"), IOStandard("LVCMOS12")),

    # Buttons
    ("user_btn_c", 0, Pins("AL11"), IOStandard("LVCMOS12")),
    ("user_btn_n", 0, Pins("AG13"), IOStandard("LVCMOS12")),
    ("user_btn_s", 0, Pins("AP20"), IOStandard("LVCMOS12")),
    ("user_btn_w", 0, Pins("AK12"), IOStandard("LVCMOS12")),
    ("user_btn_e", 0, Pins("AC14"), IOStandard("LVCMOS12")),

    # Serial
    ("serial", 0,
        Subsignal("cts", Pins("AP17")),
        Subsignal("rts", Pins("AM15")),
        Subsignal("tx",  Pins("AL17")),
        Subsignal("rx",  Pins("AH17")),
        IOStandard("LVCMOS12")
    ),

    # PCIe
    ("pcie_x1", 0,
        Subsignal("rst_n", Pins("L8"), IOStandard("LVCMOS33")),
        Subsignal("clk_p", Pins("AB8")),
        Subsignal("clk_n", Pins("AB7")),
        Subsignal("rx_p",  Pins("AE2")),
        Subsignal("rx_n",  Pins("AE1")),
        Subsignal("tx_p",  Pins("AD4")),
        Subsignal("tx_n",  Pins("AD3")),
    ),
    ("pcie_x2", 0,
        Subsignal("rst_n", Pins("L8"), IOStandard("LVCMOS33")),
        Subsignal("clk_p", Pins("AB8")),
        Subsignal("clk_n", Pins("AB7")),
        Subsignal("rx_p",  Pins("AE2 AF4")),
        Subsignal("rx_n",  Pins("AE1 AF3")),
        Subsignal("tx_p",  Pins("AD4 AE6")),
        Subsignal("tx_n",  Pins("AD3 AE5")),
    ),
    ("pcie_x4", 0,
        Subsignal("rst_n", Pins("L8"), IOStandard("LVCMOS33")),
        Subsignal("clk_p", Pins("AB8")),
        Subsignal("clk_n", Pins("AB7")),
        Subsignal("rx_p",  Pins("AE2 AF4 AG2 AJ2")),
        Subsignal("rx_n",  Pins("AE1 AF3 AG1 AJ1")),
        Subsignal("tx_p",  Pins("AD4 AE6 AG6 AH4")),
        Subsignal("tx_n",  Pins("AD3 AE5 AG5 AH3")),
    ),

    # DDR4 SDRAM
    ("ddram", 0,
        Subsignal("a",       Pins(
            "AK9 AG11 AJ10 AL8 AK10 AH8 AJ9 AG8",
            "AH9 AG10 AH13 AG9 AM13 AF8"),
            IOStandard("SSTL12_DCI")),
        Subsignal("ba",      Pins("AK8 AL12"), IOStandard("SSTL12_DCI")),
        Subsignal("bg",      Pins("AE14"), IOStandard("SSTL12_DCI")),
        Subsignal("ras_n",   Pins("AF11"), IOStandard("SSTL12_DCI")), # A16
        Subsignal("cas_n",   Pins("AE12"), IOStandard("SSTL12_DCI")), # A15
        Subsignal("we_n",    Pins("AC12"), IOStandard("SSTL12_DCI")), # A14
        Subsignal("cs_n",    Pins("AD12"), IOStandard("SSTL12_DCI")),
        Subsignal("act_n",   Pins("AD14"), IOStandard("SSTL12_DCI")),
        # Subsignal("par",     Pins("AC13"), IOStandard("SSTL12_DCI")),
        Subsignal("dm",      Pins("AH18 AD15 AM16 AP18 AE18 AH22 AL20 AP19"),
            IOStandard("POD12_DCI")),
        Subsignal("dq",      Pins(
                "AF16 AF18 AG15 AF17 AF15 AG18 AG14 AE17",
                "AA14 AC16 AB15 AD16 AB16 AC17 AB14 AD17",
                "AJ16 AJ17 AL15 AK17 AJ15 AK18 AL16 AL18",
                "AP13 AP16 AP15 AN16 AN13 AM18 AN17 AN18",
                "AB19 AD19 AC18 AC19 AA20 AE20 AA19 AD20",
                "AF22 AH21 AG19 AG21 AE24 AG20 AE23 AF21",
                "AL22 AJ22 AL23 AJ21 AK20 AJ19 AK19 AJ20",
                "AP22 AN22 AP21 AP23 AM19 AM23 AN19 AN23"),
            IOStandard("POD12_DCI"),
            Misc("PRE_EMPHASIS=RDRV_240"),
            Misc("EQUALIZATION=EQ_LEVEL2")),
        Subsignal("dqs_p",   Pins("AH14 AA16 AK15 AM14 AA18 AF23 AK22 AM21"),
            IOStandard("DIFF_POD12_DCI"),
            Misc("PRE_EMPHASIS=RDRV_240"),
            Misc("EQUALIZATION=EQ_LEVEL2")),
        Subsignal("dqs_n",   Pins("AJ14 AA15 AK14 AN14 AB18 AG23 AK23 AN21"),
            IOStandard("DIFF_POD12_DCI"),
            Misc("PRE_EMPHASIS=RDRV_240"),
            Misc("EQUALIZATION=EQ_LEVEL2")),
        Subsignal("clk_p",   Pins("AH11"), IOStandard("DIFF_SSTL12_DCI")),
        Subsignal("clk_n",   Pins("AJ11"), IOStandard("DIFF_SSTL12_DCI")),
        Subsignal("cke",     Pins("AB13"), IOStandard("SSTL12_DCI")),
        Subsignal("odt",     Pins("AF10"), IOStandard("SSTL12_DCI")),
        Subsignal("reset_n", Pins("AF12"), IOStandard("LVCMOS12")),
        Misc("SLEW=FAST"),
    ),
]

# Connectors ---------------------------------------------------------------------------------------

_connectors = [
    ("FMC_HPC0", {
        "CLK0_M2C_N"      : "E14",
        "CLK0_M2C_P"      : "E15",
        "CLK1_M2C_N"      : "F10",
        "CLK1_M2C_P"      : "G10",
        "DP0_C2M_N"       : "R5",
        "DP0_C2M_P"       : "R6",
        "DP0_M2C_N"       : "R1",
        "DP0_M2C_P"       : "R2",
        "DP1_C2M_N"       : "T3",
        "DP1_C2M_P"       : "T4",
        "DP1_M2C_N"       : "U1",
        "DP1_M2C_P"       : "U2",
        "DP2_C2M_N"       : "N5",
        "DP2_C2M_P"       : "N6",
        "DP2_M2C_N"       : "P3",
        "DP2_M2C_P"       : "P4",
        "DP3_C2M_N"       : "U5",
        "DP3_C2M_P"       : "U6",
        "DP3_M2C_N"       : "V3",
        "DP3_M2C_P"       : "V4",
        "DP4_C2M_N"       : "M5",
        "DP4_C2M_P"       : "M6",
        "DP4_M2C_N"       : "L3",
        "DP4_M2C_P"       : "L4",
        "DP5_C2M_N"       : "L5",
        "DP5_C2M_P"       : "L6",
        "DP5_M2C_N"       : "L1",
        "DP5_M2C_P"       : "L2",
        "DP6_C2M_N"       : "M3",
        "DP6_C2M_P"       : "M4",
        "DP6_M2C_N"       : "N1",
        "DP6_M2C_P"       : "N2",
        "DP7_C2M_N"       : "K3",
        "DP7_C2M_P"       : "K4",
        "DP7_M2C_N"       : "J1",
        "DP7_M2C_P"       : "J2",
        "GBTCLK0_M2C_C_N" : "V7",
        "GBTCLK0_M2C_C_P" : "V8",
        "GBTCLK1_M2C_C_N" : "77",
        "GBTCLK1_M2C_C_P" : "T8",
        "LA00_CC_N"       : "F16",
        "LA00_CC_P"       : "F17",
        "LA01_CC_N"       : "H17",
        "LA01_CC_P"       : "H18",
        "LA02_N"          : "K20",
        "LA02_P"          : "L20",
        "LA03_N"          : "K18",
        "LA03_P"          : "K19",
        "LA04_N"          : "L16",
        "LA04_P"          : "L17",
        "LA05_N"          : "J17",
        "LA05_P"          : "K17",
        "LA06_N"          : "G19",
        "LA06_P"          : "H19",
        "LA07_N"          : "J15",
        "LA07_P"          : "J16",
        "LA08_N"          : "E17",
        "LA08_P"          : "E18",
        "LA09_N"          : "G16",
        "LA09_P"          : "H16",
        "LA10_N"          : "K15",
        "LA10_P"          : "L15",
        "LA11_N"          : "A12",
        "LA11_P"          : "A13",
        "LA12_N"          : "F18",
        "LA12_P"          : "G18",
        "LA13_N"          : "F15",
        "LA13_P"          : "G15",
        "LA14_N"          : "C12",
        "LA14_P"          : "C13",
        "LA15_N"          : "C16",
        "LA15_P"          : "D16",
        "LA16_N"          : "C17",
        "LA16_P"          : "D17",
        "LA17_CC_N"       : "E10",
        "LA17_CC_P"       : "F11",
        "LA18_CC_N"       : "D10",
        "LA18_CC_P"       : "D11",
        "LA19_N"          : "C11",
        "LA19_P"          : "D12",
        "LA20_N"          : "E12",
        "LA20_P"          : "F12",
        "LA21_N"          : "A10",
        "LA21_P"          : "B10",
        "LA22_N"          : "H12",
        "LA22_P"          : "H13",
        "LA23_N"          : "A11",
        "LA23_P"          : "B11",
        "LA24_N"          : "A6",
        "LA24_P"          : "B6",
        "LA25_N"          : "C6",
        "LA25_P"          : "C7",
        "LA26_N"          : "B8",
        "LA26_P"          : "B9",
        "LA27_N"          : "A7",
        "LA27_P"          : "A8",
        "LA28_N"          : "L13",
        "LA28_P"          : "M13",
        "LA29_N"          : "J10",
        "LA29_P"          : "K10",
        "LA30_N"          : "D9",
        "LA30_P"          : "E9",
        "LA31_N"          : "E7",
        "LA31_P"          : "F7",
        "LA32_N"          : "E8",
        "LA32_P"          : "F8",
        "LA33_N"          : "C8",
        "LA33_P"          : "C9",
    }),
    ("FMC_HPC1", {
        "CLK0_M2C_N"      : "E23",
        "CLK0_M2C_P"      : "F23",
        "DP0_C2M_N"       : "AJ5",
        "DP0_C2M_P"       : "AJ6",
        "DP0_M2C_N"       : "AK3",
        "DP0_M2C_P"       : "AK4",
        "LA00_CC_N"       : "B19",
        "LA00_CC_P"       : "B18",
        "LA01_CC_N"       : "D24",
        "LA01_CC_P"       : "E24",
        "LA02_N"          : "K23",
        "LA02_P"          : "K22",
        "LA03_N"          : "J22",
        "LA03_P"          : "J21",
        "LA04_N"          : "H24",
        "LA04_P"          : "J24",
        "LA05_N"          : "G26",
        "LA05_P"          : "G25",
        "LA06_N"          : "H22",
        "LA06_P"          : "H21",
        "LA07_N"          : "C23",
        "LA07_P"          : "D22",
        "LA08_N"          : "H26",
        "LA08_P"          : "J25",
        "LA09_N"          : "F20",
        "LA09_P"          : "G20",
        "LA10_N"          : "E22",
        "LA10_P"          : "F22",
        "LA11_N"          : "A21",
        "LA11_P"          : "A20",
        "LA12_N"          : "D19",
        "LA12_P"          : "E19",
        "LA13_N"          : "C22",
        "LA13_P"          : "C21",
        "LA14_N"          : "D21",
        "LA14_P"          : "D20",
        "LA15_N"          : "A19",
        "LA15_P"          : "A18",
        "LA16_N"          : "C19",
        "LA16_P"          : "C18",
        "GBTCLK0_M2C_C_N" : "Y7",
        "GBTCLK0_M2C_C_P" : "Y8",
    }),
]

# Platform -----------------------------------------------------------------------------------------

class Platform(XilinxUSPPlatform):
    default_clk_name   = "clk125"
    default_clk_period = 1e9/125e6

    def __init__(self, toolchain="vivado"):
        XilinxUSPPlatform.__init__(self, "xczu7ev-ffvc1156-2-e", _io, _connectors, toolchain=toolchain)

    def create_programmer(self):
        return VivadoProgrammer()

    def do_finalize(self, fragment):
        XilinxUSPPlatform.do_finalize(self, fragment)
        self.add_period_constraint(self.lookup_request("clk125", loose=True), 1e9/125e6)
        self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 64]")
        self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 65]")
        self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 66]")
